package com.block.datapush.service.apipush.utils;

import cn.hutool.core.util.RandomUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Base64;


public class WangXunAesUtils {
    private static final String CHARSET_NAME = "UTF-8";
    private static final String ALGORITHM = "AES/CBC/PKCS5Padding";

    /**

     AES 中的 IV 必须是 16 字节（128位）长
     */
    private static final Integer IV_LENGTH = 16;

    /**

     AES 中的 key 的长度
     */
    private static final Integer KEY_LENGTH = 16;

    /***

     初始化key，它是一个随机生成的字节数组，用于增加加密和解密的安全性
     */
    public static String getKey() {
        return RandomUtil.randomNumbers(KEY_LENGTH);
    }

    /***

     初始化向量（IV），它是一个随机生成的字节数组，用于增加加密和解密的安全性
     */
    public static String getIV() {
        return RandomUtil.randomNumbers(IV_LENGTH);
    }

    public static String generateKey() {
        try {

//1.构造密钥生成器，指定为AES算法,不区分大小写
            KeyGenerator keygen = KeyGenerator.getInstance(ALGORITHM);
//2.生成一个128位的随机源
            keygen.init(128, new SecureRandom());
//3.产生原始对称密钥
            SecretKey secretKey = keygen.generateKey();
//4.获得原始对称密钥的字节数组
            byte[] byteKey = secretKey.getEncoded();
//5.返回密钥
            return new String(byteKey);

        }catch (Exception e){
            return null;
        }
    }

    /**

     加密

     @param input 输入

     @param key 关键

     @return {@code String}
     */
    public static String encrypt(String input, String key) {
        byte[] crypted = null;
        try {

            SecretKeySpec skey = new SecretKeySpec(key.getBytes(CHARSET_NAME), "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
            cipher.init(Cipher.ENCRYPT_MODE, skey);
            crypted = cipher.doFinal(input.getBytes(CHARSET_NAME));
        } catch (Exception e) {
            e.printStackTrace();
        }
        Base64.Encoder encoder = Base64.getEncoder();

        return encoder.encodeToString(crypted);
    }

    /**

     解密

     @param input 输入

     @param key 关键

     @return {@code String}
     */
    public static String decrypt(String input, String key) {
        byte[] output = null;
        try {
            Base64.Decoder decoder = Base64.getDecoder();
            SecretKeySpec skey = new SecretKeySpec(key.getBytes(CHARSET_NAME), "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
            cipher.init(Cipher.DECRYPT_MODE, skey);
            output = cipher.doFinal(decoder.decode(input.getBytes(CHARSET_NAME)));
            return new String(output);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("aes 解密异常 "+e);
        }

    }

    // 加密方法
    public static String encrypt(String data, String key, String iv) throws Exception {
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
        byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encrypted);
    }

    public static String encryptCS7(String value, String key, String iv) throws Exception {
        Security.addProvider(new BouncyCastleProvider());
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
        SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
        IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
        cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
        byte[] original = cipher.doFinal(value.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(original);
    }

    public static byte[] stringToByteArray(String s) {
        return s.getBytes(StandardCharsets.UTF_8);
    }

    // 解密方法
    public static String decrypt(String key, String encrypted, byte[] iv) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);

        byte[] original = cipher.doFinal(Base64.getDecoder().decode(encrypted));

        return new String(original, StandardCharsets.UTF_8);
    }

    public static String decrypt(String key, String iv, String data) {
        try {
            SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
            IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
            byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(data));
            return new String(decrypted, StandardCharsets.UTF_8);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
